#include <stdio.h>
#include "unistd.h"
#include "sdl_comm.h"

//#include "SDL/SDL_ttf.h"

#define WIDTH_SURFACE 680
#define HEIGHT_SURFACE 480
#define BPP_SURFACE 16

int quit;

int cum_SDL_init(){
	screen = NULL;
	setenv("SDL_FBDEV","/dev/fb0",1);
	//SDL_envvars("SDL_FBDEV","/dev/fb1",1);

	if((SDL_Init(SDL_INIT_VIDEO) == -1)){
		print_debug("Could not initalize SDL:%s",SDL_GetError());
			return -1;
		}


	//clearn up on exit
	//atexit(SDL_Quit);

	print_debug("SDL initalized.");
	/*
	if(SDL_VideoModeOK(WIDTH_SURFACE,HEIGHT_SURFACE,BPP_SURFACE,SDL_SWSURFACE|SDL_ANYFORMAT) == 0){
		print_debug(stderr,"SDL_VideoModeOk error.......");
		return -1;
	}else{
		print_debug("test set video mode ok!!");
	}
	*/
	SDL_VideoInfo *info = SDL_GetVideoInfo();
	print_debug("SDL_GetVideoInfo:%d,%d,%d",info->current_h,info->current_w,info->vfmt->BitsPerPixel);


	//screen = SDL_GetVideoSurface();


	screen = SDL_SetVideoMode(WIDTH_SURFACE,HEIGHT_SURFACE,BPP_SURFACE,SDL_ANYFORMAT|SDL_HWSURFACE);
	if(screen == NULL){
		print_debug("Couldn't set %d*%d*%d video mode:%s",
				WIDTH_SURFACE,HEIGHT_SURFACE,BPP_SURFACE,SDL_GetError());
		return -1;
	}

	print_debug("set %d*%d*%d video mode ok!",
					screen->w,screen->h,screen->format->BitsPerPixel);
	//SDL_envvars
	//SDL_VideoModeOK();
	//SDL_CreateRGBSurface()
	videoinfo = SDL_GetVideoInfo();
	return 0;
}

static void quit_tutorial( int code )
{
    /*
     * Quit SDL so we can release the fullscreen
     * mode and restore the previous video settings,
     * etc.
     */
    //SDL_Quit( );
	quit = -1;
    cum_SDL_Quit();
    printf("exit .............\n");
    /* Exit program. */
    exit( code );
}

static void handle_key_down( SDL_keysym* keysym )
{

    /*
     * We're only interested if 'Esc' has
     * been presssed.
     *
     * EXERCISE:
     * Handle the arrow keys and have that change the
     * viewing position/angle.
     */
    switch( keysym->sym ) {
    case SDLK_ESCAPE:
        quit_tutorial( 0 );
        break;
    case SDLK_SPACE:
        //should_rotate = !should_rotate;
        break;
    default:
        break;
    }

}

void process_events( void )
{
    /* Our SDL event placeholder. */
    SDL_Event event;

    /* Grab all the events off the queue. */
    while( SDL_PollEvent( &event ) ) {

        switch( event.type ) {
        case SDL_KEYDOWN:
            /* Handle key presses. */
        	printf("sdl keydown process..........\n");
            handle_key_down( &event.key.keysym );
            break;
        case SDL_QUIT:
            /* Handle quit requests (like Ctrl-c). */
            quit_tutorial( 0 );
            break;
        }

    }

}

int cum_SDL_init_with_OpenGL(){
	/* Information about the current video settings. */
	const SDL_VideoInfo* info = NULL;
	/* Dimensions of our window. */
	int width = 0;
	int height = 0;
	/* Color depth in bits of our window. */
	int bpp = 0;
	/* Flags we will pass into SDL_SetVideoMode. */
	int flags = 0;

	/* First, initialize SDL's video subsystem. */
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
		/* Failed, exit. */
		fprintf( stderr, "Video initialization failed: %s\n",
			 SDL_GetError( ) );
		return -1;
	}

	/* Let's get some video information. */
	info = SDL_GetVideoInfo( );

	if( !info ) {
		/* This should probably never happen. */
		fprintf( stderr, "Video query failed: %s\n",
			 SDL_GetError( ) );
		return -1;
	}

	/*
	 * Set our width/height to 640/480 (you would
	 * of course let the user decide this in a normal
	 * app). We get the bpp we will request from
	 * the display. On X11, VidMode can't change
	 * resolution, so this is probably being overly
	 * safe. Under Win32, ChangeDisplaySettings
	 * can change the bpp.
	 */
	width = 640;
	height = 480;
	bpp = info->vfmt->BitsPerPixel;

	/*
	 * Now, we want to setup our requested
	 * window attributes for our OpenGL window.
	 * We want *at least* 5 bits of red, green
	 * and blue. We also want at least a 16-bit
	 * depth buffer.
	 *
	 * The last thing we do is request a double
	 * buffered window. '1' turns on double
	 * buffering, '0' turns it off.
	 *
	 * Note that we do not use SDL_DOUBLEBUF in
	 * the flags to SDL_SetVideoMode. That does
	 * not affect the GL attribute state, only
	 * the standard 2D blitting setup.
	 */
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	/*
	 * We want to request that SDL provide us
	 * with an OpenGL window, in a fullscreen
	 * video mode.
	 *
	 * EXERCISE:
	 * Make starting windowed an option, and
	 * handle the resize events properly with
	 * glViewport.
	 */
	flags = SDL_OPENGL | SDL_FULLSCREEN;

	/*
	 * Set the video mode
	 */
	if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
		/*
		 * This could happen for a variety of reasons,
		 * including DISPLAY not being set, the specified
		 * resolution not being available, etc.
		 */
		fprintf( stderr, "Video mode set failed: %s\n",
			 SDL_GetError( ) );
		return -1;
	}
	return 0;
}

int cum_SDL_Quit(){
	printf("Quiting SDL.\n");
	SDL_Quit();
	printf("Quiting...\n");
	return 0;
}

void display_bmp(char *file_name){
	SDL_Surface *image;
	image = SDL_LoadBMP(file_name);
	SDL_SetAlpha(image,0,100);
	uint32_t rgb = SDL_MapRGB(videoinfo->vfmt,7,38,103);
	SDL_SetColorKey(image,0,rgb);

	if(image == NULL){
		fprintf(stderr,"Couldn't load %s:%s\n",file_name,SDL_GetError());
		return;
	}
	if(image->format->palette && screen->format->palette){
		SDL_SetColors(screen,image->format->palette->colors,0,
				image->format->palette->ncolors);
	}
	if(SDL_BlitSurface(image,NULL,screen,NULL) < 0){
		fprintf(stderr,"BlitSurface error:%s\n",SDL_GetError());
	}
	SDL_UpdateRect(screen,0,0,image->w,image->h);
	SDL_FreeSurface(image);
}

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

/*
 * Return the pixel value at (x, y)
 * NOTE: The surface must be locked before calling this!
 */
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }
}

void use_putpixel(int x, int y){
	/* Code to set a yellow pixel at the center of the screen */
	Uint32 yellow;

	/* Map the color yellow to this display (R=0xff, G=0xFF, B=0x00)
	   Note:  If the display is palettized, you must set the palette first.
	*/
	yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
	/*
	x = screen->w / 2;
	y = screen->h / 2;
	*/
	/* Lock the screen for direct access to the pixels */
	if ( SDL_MUSTLOCK(screen) ) {
		if ( SDL_LockSurface(screen) < 0 ) {
			fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
			return;
		}
	}

	putpixel(screen, x, y, yellow);

	if ( SDL_MUSTLOCK(screen) ) {
		SDL_UnlockSurface(screen);
	}
	/* Update just the part of the display that we've changed */
	SDL_UpdateRect(screen, x, y, 1, 1);

	return;
}
